﻿using PBO.Data;
using PBO.Game.BattleClass;
using PBO.Game.Img;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;

namespace PBO.Game.BattleClass
{
    public class Move
    {

        public Move(int id, Pokemon owner, int ppUp) : this(GameService.GetMove(id), owner, ppUp) { }

        public Move(MoveData data, Pokemon owner, bool ppUp) : this(data, owner, ppUp ? 3 : 0) { }

        public Move(MoveData data, Pokemon owner, int ppUp)
        {
            this.Data = data;
            this.Owner = owner;
            this.Power = data.Power;
            this.Target = data.Target;
            this.Protectable = data.Details[6];
            this.Substitute = data.Details[5];
            this.MaxPP = data.PP > 1 ? (data.PP + data.PP * ppUp / 5) : data.PP;
            this.PP = this.MaxPP;
            this.Type = data.Type;
        }

        #region props

        public Pokemon Owner { get; private set; }
        public MoveData Data { get; private set; }
        public BattleType Type { get; private set; }

        public int Power { get; private set; }

        public int Priority
        {
            get { return this.Data.Priority; }
        }

        public MoveTarget Target { get; private set; }

        public bool Contact
        {
            get { return this.Data.Details[0]; }
        }

        public bool Sound
        {
            get { return this.Data.Details[1]; }
        }

        public bool KingRock
        {
            get { return this.Data.Details[2]; }
        }

        public bool Snatchable
        {
            get { return this.Data.Details[3]; }
        }

        public bool AttackAtTarget
        {
            get { return this.Data.Details[4]; }
        }

        public bool Substitute { get; private set; }

        public bool Protectable { get; private set; }

        public bool Punch
        {
            get { return this.Data.Details[7]; }
        }

        public bool EverUsed { get; private set; }

        public void ResetUsed()
        {
            this.EverUsed = false;
        }

        #endregion

        #region pp

        public int MaxPP { get; private set; }

        private bool ppChanged;
        private int _PP;
        public int PP
        {
            get
            {
                return _PP;
            }
            set
            {
                int pp = InRange(value, 0, this.MaxPP);
                if (pp != _PP)
                {
                    _PP = pp;
                    if (_image != null)
                        ppChanged = true;
                }
            }
        }

        #endregion

        public void Used()
        {
            if (this.PP > 0)
            {
                this.PP--;
                this.EverUsed = true;
            }
        }

        /// <summary>
        /// 技能诅咒
        /// </summary>
        public void UpdateCourse(Pokemon pm)
        {
            bool haveGhost = pm.HaveType(BattleType.Ghost);
            this.Target = haveGhost ? MoveTarget.选一 : MoveTarget.自身;
            this.Substitute = haveGhost;
            this.Protectable = haveGhost;
        }

        #region set

        private bool typeChanged;

        public void SetType(BattleType type)
        {
            this.Type = type;
            if (_image != null)
                typeChanged = true;
        }

        public void SetPower(int powerValue)
        {
            this.Power = powerValue;
        }

        #endregion

        #region image

        private Bitmap _image;
        public Bitmap Image
        {
            get
            {
                if (_image == null)
                    _image = GetMoveImage(this);
                if (ppChanged)
                {
                    using (Graphics graph = Graphics.FromImage(_image))
                    {
                        string str = "PP " + PP + "/" + MaxPP;
                        graph.FillRectangle(new SolidBrush(Properties.Resources.Move.GetPixel(52, 33)), new Rectangle(52, 33, 56, 12));
                        graph.DrawString(str, PPFont, Brushes.Black, 52, 33);
                    }
                    ppChanged = false;
                }
                if (typeChanged)
                {
                    using (Graphics graph = Graphics.FromImage(_image))
                    {
                        DrawMoveFrame(graph, (Bitmap)this.Type.GetImage());
                    }
                    typeChanged = false;
                }
                return _image;
            }
        }

        #endregion

        #region static

        private static Font PPFont = new Font(ImageHelper.FONT_NAME, 12, FontStyle.Bold, GraphicsUnit.Pixel);
        private static Font NameFont = new Font(ImageHelper.FONT_NAME, 16, FontStyle.Regular, GraphicsUnit.Pixel);

        private static GraphicsPath[] TypePath;
        static Move()
        {
            //TypePath = Enumerable.Repeat(new GraphicsPath(), 2).ToArray();
            TypePath = new GraphicsPath[] { new GraphicsPath(), new GraphicsPath() };

            TypePath[0].AddRectangle(new Rectangle(4, 50, 116, 1));
            TypePath[0].AddRectangle(new Rectangle(3, 49, 118, 1));
            TypePath[0].AddRectangle(new Rectangle(3, 48, 5, 1));
            TypePath[0].AddRectangle(new Rectangle(116, 48, 5, 1));

            TypePath[1].AddRectangle(new Rectangle(5, 4, 114, 1));
            TypePath[1].AddRectangle(new Rectangle(4, 5, 116, 5));
            TypePath[1].AddRectangle(new Rectangle(7, 10, 1, 1));
            TypePath[1].AddRectangle(new Rectangle(116, 10, 1, 1));
        }

        private static Bitmap GetMoveImage(Move moveVal)
        {
            Bitmap newImg = new Bitmap(Properties.Resources.Move);
            using (Graphics graph = Graphics.FromImage(newImg))
            {
                if (moveVal.Type != BattleType.None)
                    DrawMoveFrame(graph, (Bitmap)moveVal.Type.GetImage());
                graph.DrawString(moveVal.Data.Name, NameFont, Brushes.Black, 16, 14);
                graph.DrawString("PP " + moveVal.PP + "/" + moveVal.MaxPP, PPFont, Brushes.Black, 52, 33);
            }
            return newImg;
        }

        private static void DrawMoveFrame(Graphics graph, Bitmap typeImg)
        {
            Color color1 = typeImg.GetPixel(5, 0);
            Color color2 = typeImg.GetPixel(5, 3);
            Color color3 = typeImg.GetPixel(5, typeImg.Height - 1);

            Rectangle rect1 = new Rectangle(117, 7, 4, 43);
            Rectangle rect2 = new Rectangle(3, 7, 4, 43);

            LinearGradientBrush brush = default(LinearGradientBrush);
            brush = new LinearGradientBrush(new Rectangle(0, 0, 118, 3), color2, color3, LinearGradientMode.Vertical);
            graph.FillPath(brush, TypePath[0]);
            brush = new LinearGradientBrush(new Rectangle(0, 0, 116, 7), color2, color1, LinearGradientMode.Vertical);
            graph.FillPath(brush, TypePath[1]);

            brush = new LinearGradientBrush(rect1, color3, color2, LinearGradientMode.Horizontal);
            graph.FillRectangle(brush, rect1);

            brush = new LinearGradientBrush(rect2, color2, color3, LinearGradientMode.Horizontal);
            graph.FillRectangle(brush, rect2);

            graph.DrawImageUnscaled(typeImg, 14, 32);
        }

        #endregion

        public static int InRange(int value, int min, int max)
        {
            int v = Math.Max(min, value);
            v = Math.Min(max, v);
            return v;
        }

    }
}
